24. Cookie, Session

设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.itguigu.cookie;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class SetCookieTest extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建 cookie
Cookie cookie = new Cookie("stuName", "zhangsan");
// 响应给客户端
response.addCookie(cookie);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.itguigu.cookie;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class GetCookieTest extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
System.out.println("cookie name" + cookie.getName());
System.out.println("cookie value" + cookie.getValue());
}
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.itguigu.cookie;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class SetCookieTest extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 修改 cookie 方式1,直接覆盖
Cookie cookie = new Cookie("stuName", "new Value");
response.addCookie(cookie);

// 修改 cookie 方式2
Cookie[] cookies = request.getCookies();
for (Cookie cookie2 : cookies) {
if ("stuName".equals(cookie2.getName())) {
cookie2.setValue("new Value2");
response.addCookie(cookie2);
break;
}
}
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

有效性

cookie 默认为会话级别,与浏览器有关(关闭或者换一个浏览器则失效)

持久性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.itguigu.cookie;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class SetCookieTest extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("stuName", "new Value");
cookie.setMaxAge(30); //30s 后失效 。当数字大于0时,表示 xx 秒后失效。等于 0 时表示立即失效。小于0 时表示默认会话级别,关闭浏览器就会失效。
response.addCookie(cookie);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

有效路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.itguigu.cookie;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class SetCookieTest extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("stuName", "new Value");
// 有效路径为当前项目下的 a 目录。request.getContextPath() 获取的是项目根目录
cookie.setPath(request.getContextPath() + "a");
response.addCookie(cookie);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

缺陷

cookie 的 value 只能为 string 类型

cookie 是存放在浏览器中的,相对来说不安全,可能被伪造等

Session

session 的 value 是 object 类型。session的类型是 HttpSession

原理

服务器创建 session,同时创建一个 cookie,cookie 的 key 为 JSESSIONID,value 为 session 的 id。并将该 cookie 响应给客户端,以后客户端再请求时,携带 cookie 就行,服务器端会根据 cookie 的 value 找到对应的 session。

获取

Servlet 中使用 request.getSession() 获取

jsp 中直接使用 session 隐含对象获取

1
2
3
4
5
6
7
8
9
10
11
// servlet 中获取 session
HttpSession session = request.getSession();
System.out.println(session.getId());

// 设置值,修改值, 移除值
session.setAttribute("name", "value");
session.getAttribute("name");
session.removeAttribute("name");

// jsp 中获取 session
<%=session.getId()%>

有效性

默认有效性:当前会话(因为 cookie 是会话级别)

如果需要持久化 session,需要持久化 cookie。 另外 Servlet session 的存活时间为 30 min,如需更改,可以修改 web.xml 内容。或者通过在代码中设置。

方式1

1
2
3
<session-config>
<session-timeout>30</session-timeout>
</session-config>

方式2

1
2
3
4
5
6
7
8
// servlet 中获取 session
HttpSession session = request.getSession();

// 持久化 session 时间为 30 min,值大于0表示在多少秒后失效,小于等于0表示永不失效(Tomcat >=7),如果要立即失效,需要调用 invalidate 方法
session.setMaxInactiveInterval(60*60*30);

// 让其立即失效(所有)
session.invalidate();

钝化和活化

钝化:服务器关闭时,将 session 及数据从内存中序列化(对象需要实现 Serializable 接口)到硬盘上的过程

活化:服务器关闭时,将 session 及数据从硬盘中反序列化(对象需要实现 Serializable 接口)到内存中的过程

表单重复提交

转发,或者多次点击多可能造成多次提交。解决方法是下发一个 UUID 到隐藏域中,并将其存在 Session 中,表单每次提交对比隐藏域中的 UUID 和 Session 中的 UUID是否相等即可。如果相等则是第一次提交,并将 Session 域中的 UUID 删除。